use crate::{db::connect_to_db, handlers::get_user, post::Post, user::UserPost};
use anyhow::{Context, Result};
use futures::StreamExt;
use mongodb::{
    bson::{doc, from_document, spec::BinarySubtype, Binary},
    Database,
};
use teloxide::prelude2::*;
use teloxide::{
    payloads::EditMessageCaptionInlineSetters,
    prelude::Requester,
    types::{InlineKeyboardButton, InlineKeyboardButtonKind, InlineKeyboardMarkup},
};
use uuid::Uuid;
pub async fn get_post_info(bot: AutoSend<Bot>, q: CallbackQuery, data: &str) -> Result<()> {
    let pos = data.find(' ').unwrap();
    let (post_id_str, page_num) = data.split_at(pos);
    println!("{}", page_num);
    let user_id = q.from.id;
    let user = get_user(user_id).await?;
    let message_id = q.message.clone().unwrap().id;
    let chat_id = q.message.clone().unwrap().chat_id();
    let post_id = Uuid::parse_str(post_id_str)?;
    let bin_id = Binary {
        subtype: BinarySubtype::Uuid,
        bytes: post_id.as_bytes().to_vec(),
    };
    let db = connect_to_db().await?;
    let user_post = get_user_post(user.id, bin_id.clone(), &db).await?;
    let post = get_post(bin_id, &db).await?;
    let text = format!(
        r##"{:#?}
url: {}
favourite: {}
read: {}
"##,
        post.title,
        user_post.original_url(),
        user_post.favourite(),
        user_post.read()
    );
    let archive_button = {
        if user_post.read() {
            InlineKeyboardButton::new(
                "unarchive",
                InlineKeyboardButtonKind::CallbackData(format!("unarchive {}", post_id_str)),
            )
        } else {
            InlineKeyboardButton::new(
                "archive",
                InlineKeyboardButtonKind::CallbackData(format!("archive {}", post_id_str)),
            )
        }
    };
    let favourite_button = {
        if user_post.favourite() {
            InlineKeyboardButton::new(
                "unfavourite",
                InlineKeyboardButtonKind::CallbackData(format!("unfavourite {}", post_id_str)),
            )
        } else {
            InlineKeyboardButton::new(
                "favourite",
                InlineKeyboardButtonKind::CallbackData(format!("favourite {}", post_id_str)),
            )
        }
    };
    let back_button = InlineKeyboardButton::new(
        "back",
        InlineKeyboardButtonKind::CallbackData(format!("page{}", page_num)),
    );
    let buttons = vec![vec![archive_button, favourite_button], vec![back_button]];
    let reply_markup = InlineKeyboardMarkup::new(buttons);
    bot.edit_message_text(chat_id, message_id, text)
        .reply_markup(reply_markup)
        .await?;
    Ok(())
}

async fn get_user_post(user_id: Uuid, post_id: Binary, db: &Database) -> Result<UserPost> {
    let user_coll = db.collection::<UserPost>("userposts");
    let match1_aggr = doc! {
        "$match": {
        "user_id": user_id,
        "post_id": post_id,
        }
    };
    /*let proj_aggr = doc! {
        "$project" :{
            "posts": 1,
        }
    };*/
    /*let unset_aggr = doc! {
        "$unset": "_id"
    };
    let unwind_aggr = doc! {
        "$unwind": "$posts"
    };
    let replace_with_aggr = doc! {
        "$replaceWith": {
            "$mergeObjects":
        [
            {"post_id": 0, "original_url":0, /*"show_real_url": 0,*/}, "$posts"
        ]
    }
    };
    let match2_aggr = doc! {
        "$match": {
            "post_id": post_id,
    }
    };*/
    let pipeline = [
        match1_aggr,
        /*proj_aggr,
        unset_aggr,
        unwind_aggr,
        replace_with_aggr,
        match2_aggr,*/
    ];
    let post = user_coll
        .aggregate(pipeline, None)
        .await
        .context("lalalala")?
        .next()
        .await
        .context("get_user_post failed")??;
    Ok(from_document::<UserPost>(post)?)
}
async fn get_post(post_id: Binary, db: &Database) -> Result<Post> {
    let coll = db.collection::<Post>("posts");
    let match_aggr = doc! {
        "$match": {
            "id": post_id
        }
    };
    let limit_aggr = doc! {
        "$limit": 1_i32
    };
    let pipeline = [match_aggr, limit_aggr];
    let post = coll
        .aggregate(pipeline, None)
        .await
        .context("hahahahla")?
        .next()
        .await
        .context("get_post failed")??;
    Ok(from_document::<Post>(post)?)
}
